import math
import collections


def bleu(pred_seq, label_seq, k):  # @save
    """计算BLEU"""
    pred_tokens, label_tokens = pred_seq.split(' '), label_seq.split(' ')
    len_pred, len_label = len(pred_tokens), len(label_tokens)
    # print(pred_tokens,label_tokens,len_pred, len_label )
    # 只要预测的比label短，这个分数就不是1
    score = math.exp(min(0, 1 - len_label / len_pred))
    # print(score)

    for n in range(1, k + 1):
        num_matches, label_subs = 0, collections.defaultdict(int)
        for i in range(len_label - n + 1):
            label_subs[' '.join(label_tokens[i: i + n])] += 1
        for i in range(len_pred - n + 1):
            if label_subs[' '.join(pred_tokens[i: i + n])] > 0:
                num_matches += 1
                label_subs[' '.join(pred_tokens[i: i + n])] -= 1
        # {'你': 1, '1': 2, '2': 1, '好': 1})
        # '你 不 1 好'
        # {'你': 0, '1': 1, '2': 1, '好': 0})
        # {'你': 0, '1': 1, '2': 1, '好': 0, '不': 0})
        # {'你': 0, '1': 1, '2': 1, '好': 0, '不': 0}
        # print(num_matches,len_pred - n + 1, label_subs,)
        # num_matches / (len_pred - n + 1) 代表匹配接近程度
        # math.exp(min(0, 1 - len_label / len_pred)) 代表句子长度的接近程度
        score *= math.pow(num_matches / (len_pred - n + 1), math.pow(0.5, n))
    return score


# 将标签编成预测词频度字典，把预测按照相同的分割处理，如果出现在频度字典中，其匹配值减掉1，直至为0.
print(bleu('你 不 1 不 好 1', '你 不 1 不 好 1', 3))
